/* ****************************************************************************
 *
 * Copyright (c) Microsoft Corporation. 
 *
 * This source code is subject to terms and conditions of the Microsoft Public License. A 
 * copy of the license can be found in the License.html file at the root of this distribution. If 
 * you cannot locate the  Microsoft Public License, please send an email to 
 * dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
 * by the terms of the Microsoft Public License.
 *
 * You must not remove this notice, or any other, from this software.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 * ***************************************************************************/


#if !defined(AFX_FIELDREGMAP_H__EF4E6FEC_808F_46C2_ADFF_52E9BF0E4BDC__INCLUDED_)
#define AFX_FIELDREGMAP_H__EF4E6FEC_808F_46C2_ADFF_52E9BF0E4BDC__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <math.h>
#include "FieldMap.h"

namespace contour
{
	
/*! \brief A field objet on a regular latice with constant dx, dy

  \ingroup FieldGroup
	*/
template<typename T>
class TFieldRegMap : public TFieldMap<T>  
{
public:
	TFieldRegMap(const std::TSTLMatrix<T>& vData= std::TSTLMatrix<T>(0,0), T _dLeft=0, T _dTop=1, T _dDx=1, T _dDy=1)
		: TFieldMap<T>(vData)
	{
		m_limits.left=_dLeft;
		m_limits.top=_dTop;
		m_limits.right=_dLeft+(GetColSize()-1)*_dDx;
		m_limits.bottom=_dTop-(GetRowSize()-1)*_dDy;
	}
	
	virtual ~TFieldRegMap(){};
	
	virtual T Eval(T x, T y)
	{	
		size_t xi, yi;
		T alphaxi;
		T alphayi;
		
		T dx=GetLimits().GetWidth()/(GetColSize()-1);
		T dy=GetLimits().GetHeight()/(GetRowSize()-1);
		
		// truncating x,y
		x=__max(m_limits.left, __min( m_limits.right , x) );
		y=__min(m_limits.top, __max( m_limits.bottom, y));
		
		// getting index
		xi=(size_t) floor((x-GetLimits().left)/dx);
		yi=(size_t) floor((GetLimits().top-y)/dy);
		
		alphaxi=(x-xi*dx-m_limits.left)/dx;
		alphayi=(m_limits.top-y-yi*dy)/dy;
		
		if ( (xi == GetColSize()-1) && (yi == GetRowSize()-1) )
		{
			return GetVal(yi,xi);
		}
		else if ( xi == GetColSize()-1 )
		{
			ASSERT(yi>=0);
			ASSERT(yi < GetRowSize() - 1);
			// interpolating
			return GetVal(yi,xi)*(1-alphayi)+GetVal(yi+1,xi)*alphayi;
		}
		else if (yi == GetRowSize()-1)
		{
			ASSERT(xi>=0);
			ASSERT(xi < GetColSize() - 1);
			// interpolating
			return GetVal(yi,xi)*(1-alphaxi)+GetVal(yi,xi+1)*alphaxi;
		}
		else
		{
			ASSERT(yi>=0);
			ASSERT(yi < GetRowSize() - 1);
			ASSERT(xi>=0);
			ASSERT(xi < GetColSize() - 1);
			// interpolating
			return GetVal(yi,xi)*(1-alphaxi)*(1-alphayi)
				+GetVal(yi+1,xi)*(1-alphaxi)*alphayi
				+GetVal(yi+1,xi+1)*alphaxi*alphayi
				+GetVal(yi,xi+1)*alphaxi*(1-alphayi);
		}
	};
};
	
};

#endif // !defined(AFX_FIELDREGMAP_H__EF4E6FEC_808F_46C2_ADFF_52E9BF0E4BDC__INCLUDED_)
